<?php


namespace app\xiangji\services;



use app\common\facades\auth\Auth;
use app\common\models\UserRecharge;
use app\Request;
use app\xiangji\exception\GatewayException;
use app\xiangji\exception\ModelNotFoundException;
use app\xiangji\exception\ServiceUnavailableException;
use think\facade\Db;

class UserRechargeService
{
    private $userRecharge;
    private $payService;

    public function __construct(UserRecharge $userRecharge, PayService $payService)
    {
        $this->userRecharge     = $userRecharge;
        $this->payService    = $payService;
    }

    /**
     * @todo 小程序支付
     * @param Request $request
     * @return array
     * @throws ServiceUnavailableException
     */
    public function miniprogram(Request $request)
    {
        $user = Auth::guard('api')->user();
        Db::startTrans();
        try {
            // 创建充值订单
            $recharge = $this->userRecharge->createRow([
                'user_id'       => $user->id,
                'openid'    => $user->openId,
                'pay_way'   => $this->userRecharge::PAY_WAY_WECHAT,
                'status'    => $this->userRecharge::PAY_NOTPAY,
                'total_fee' => $request->post('fee', 1),
                'order_type'=> $request->post('order_type', 0),
            ]);
            // 微信统一下单
            $unified_order = $this->payService->wechat()->miniprogram([
                'openid'        => $recharge->openid,
                'body'          => $request->post('desc', '恋爱时光增值服务'),
                'out_trade_no'  => $recharge->order_no,
                'total_fee'     => $recharge->total_fee,
                'notify_url'    => env('app.url') . '/weapp/pay/notify/wechat',
            ], $order_data);
            // 记录下单原始值
            $recharge->log()->save(['order_result' => json_encode($order_data)]);
            Db::commit();
        }catch (\Exception $exception){
            Db::rollback();
            throw new ServiceUnavailableException('系统错误，请稍后再试');
        }
        return $unified_order;
    }

    /**
     * @todo 查询充值订单支付情况
     * @param string $order_no
     * @return UserRecharge|array|\think\Model|null
     * @throws GatewayException
     * @throws ModelNotFoundException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function queryPayStatus(string $order_no)
    {
        $recharge = $this->userRecharge->where('order_no', '=', $order_no)->find();
        if (!$recharge){
            throw new ModelNotFoundException('未找到该订单信息');
        }
        // 不同支付途径用不同的方式主动查询
        if ($recharge->pay_way == UserRecharge::PAY_WAY_WECHAT){
            $recharge = $this->queryWxPayOrder($recharge);
        }
        return $recharge;
    }

    /**
     * @todo 根据充值订单主动查询微信支付情况
     * @param UserRecharge $recharge
     * @return UserRecharge
     * @throws GatewayException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function queryWxPayOrder(UserRecharge $recharge)
    {
        // 支付状态已更改则不用主动查询微信端
        if ($recharge->status != UserRecharge::PAY_NOTPAY) return $recharge;
        // 主动查询微信端
        $result = $this->payService->wechat()->queryWxPayByOutTradeNumber($recharge->order_no);
        if ($result['return_code'] != 'SUCCESS'){
            throw new GatewayException('微信支付查询网关错误');
        }
        if ($result['result_code'] != 'SUCCESS'){
            // 订单有误
            $recharge->save([
                'err_code'      => $result['err_code'],
                'err_code_des'  => $result['err_code_des'],
                'status'        => UserRecharge::PAY_FAIL
            ]);
        }
        // 交易状态trade_state不为 SUCCESS，则只返回out_trade_no（必传）和attach（选传）
        if ($result['trade_state'] != 'SUCCESS'){
            switch ($result['trade_state']){
                case 'SUCCESS':
                    $pay_status = UserRecharge::PAY_SUCCESS;
                    break;
                case 'PAYERROR':
                case 'REVOKED':
                case 'CLOSED':
                    $pay_status = UserRecharge::PAY_FAIL;
                    break;
                default:
                    $pay_status = UserRecharge::PAY_NOTPAY;

            }
            $recharge->save([
                'trade_state'   => $result['trade_state'],
                'status'        => $pay_status
            ]);
        }
        // 正常支付成功返回记录结果
        $recharge->save([
            'status'            => UserRecharge::PAY_SUCCESS,
            'paid_fee'          => $result['total_fee'],
            'transaction_id'    => $result['transaction_id'],
            'trade_state'       => $result['trade_state'],
            'pay_time'          => strtotime($result['time_end']),
        ]);
        // 记录支付订单返回结果
        $recharge->log->save(['pay_result' => json_encode($result)]);
        // 已支付，更新订单信息，并关闭订单
        $this->payService->wechat()->closeWxPayOrder($recharge->order_no);
        return $recharge;
    }

    /**
     * @todo 微信支付回调方法
     * @return mixed
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function wxPayNotify()
    {
        return $this->payService->wechat()->payment->handlePaidNotify(function ($message, $fail){
            $recharge = $this->userRecharge->where('order_no', '=', $message['out_trade_no'])->find();
            if (!$recharge || $recharge['status'] == UserRecharge::PAY_SUCCESS || $recharge['status'] == UserRecharge::PAY_FAIL){
                return true;
            }
            if ($message['return_code'] != 'SUCCESS'){
                return $fail('通信失败，请稍后再通知我');
            }
            if ($message['result_code'] != 'SUCCESS'){
                // 订单有误
                $recharge->save([
                    'err_code'      => $message['err_code'],
                    'err_code_des'  => $message['err_code_des'],
                    'status'        => UserRecharge::PAY_FAIL
                ]);
            }
            // 正常支付成功返回记录结果
            $recharge->save([
                'status'            => UserRecharge::PAY_SUCCESS,
                'paid_fee'          => $message['total_fee'],
                'transaction_id'    => $message['transaction_id'],
                'trade_state'       => 'SUCCESS',
                'pay_time'          => strtotime($message['time_end']),
            ]);
            // 记录支付订单返回结果
            $recharge->log->save(['pay_result' => json_encode($message)]);
            // 已支付，更新订单信息，并关闭订单
            $this->payService->wechat()->closeWxPayOrder($recharge->order_no);
        });
    }
}
